package com.huahua.api.service.impl;

import com.huahua.api.entity.enums.TtsStatus;
import com.huahua.api.entity.param.TtsCompleteParam;
import com.huahua.api.entity.param.TtsCreateParam;
import com.huahua.api.entity.pojo.TtsRecord;
import com.huahua.api.entity.vo.TtsRecordVo;
import com.huahua.api.exception.CommonException;
import com.huahua.api.repository.TtsRecordRepository;
import com.huahua.api.service.TtsService;
import com.huahua.api.util.CheckUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

/**
 * @author Huahua-Ai
 * @date 2025-01-10 15:00:00
 * @description TTS服务实现
 */
@Service
public class TtsServiceImpl implements TtsService {

    private static final Logger log = LoggerFactory.getLogger(TtsServiceImpl.class);

    @Autowired
    private TtsRecordRepository ttsRecordRepository;

    @Override
    public Mono<TtsRecordVo> createTask(TtsCreateParam param) {
        return Mono.fromCallable(() -> {
                    CheckUtil.checkStrNotBlank(param.getTextContent(),
                            new CommonException("文字内容不能为空"));
                    CheckUtil.checkTrue(param.getTextContent().length() <= 10000,
                            new CommonException("文字内容长度不能超过10000字符"));

                    if (param.getTemperature() != null) {
                        CheckUtil.checkTrue(param.getTemperature().doubleValue() >= 0
                                        && param.getTemperature().doubleValue() <= 1,
                                new CommonException("temperature参数必须在0-1之间"));
                    }

                    if (param.getTopP() != null) {
                        CheckUtil.checkTrue(param.getTopP().doubleValue() >= 0
                                        && param.getTopP().doubleValue() <= 1,
                                new CommonException("topP参数必须在0-1之间"));
                    }

                    return param;
                })
                .flatMap(validParam -> {
                    TtsRecord record = new TtsRecord();
                    record.setTextContent(validParam.getTextContent());
                    record.setStatus(TtsStatus.PENDING.getCode());
                    record.setPrompt(validParam.getPrompt());
                    record.setTemperature(validParam.getTemperature());
                    record.setTopP(validParam.getTopP());
                    record.setTopK(validParam.getTopK());
                    record.setRefineMaxNewToken(validParam.getRefineMaxNewToken());
                    record.setInferMaxNewToken(validParam.getInferMaxNewToken());
                    record.setSkipRefine(validParam.getSkipRefine());
                    record.setCustomVoice(validParam.getCustomVoice());
                    record.setCreatedTime(LocalDateTime.now());

                    return ttsRecordRepository.save(record);
                })
                .map(TtsRecordVo::from)
                .doOnSuccess(vo -> log.info("创建TTS任务成功，ID: {}", vo.getId()))
                .doOnError(e -> log.error("创建TTS任务失败", e));
    }

    @Override
    public Mono<TtsRecordVo> getTaskStatus(Long id) {
        CheckUtil.checkNotNull(id, new CommonException("任务ID不能为空"));

        return ttsRecordRepository.findById(id)
                .switchIfEmpty(Mono.error(new CommonException("任务不存在")))
                .map(TtsRecordVo::from)
                .doOnError(e -> log.error("获取TTS任务状态失败，ID: {}", id, e));
    }

    @Override
    public Mono<TtsRecordVo> completeTask(TtsCompleteParam param) {
        return Mono.fromCallable(() -> {
                    CheckUtil.checkNotNull(param.getRecordId(),
                            new CommonException("记录ID不能为空"));
                    CheckUtil.checkNotNull(param.getSuccess(),
                            new CommonException("成功标识不能为空"));

                    if (param.getSuccess()) {
                        CheckUtil.checkStrNotBlank(param.getFileUrl(),
                                new CommonException("文件地址不能为空"));
                    } else {
                        CheckUtil.checkStrNotBlank(param.getErrorMessage(),
                                new CommonException("错误信息不能为空"));
                    }

                    return param;
                })
                .flatMap(validParam -> ttsRecordRepository.findById(validParam.getRecordId()))
                .switchIfEmpty(Mono.error(new CommonException("任务不存在")))
                .flatMap(record -> {
                    if (!TtsStatus.PROCESSING.getCode().equals(record.getStatus())) {
                        return Mono.error(new CommonException("任务状态不正确，当前状态: " + record.getStatus()));
                    }

                    LocalDateTime now = LocalDateTime.now();
                    record.setCompletedTime(now);

                    if (param.getSuccess()) {
                        record.setStatus(TtsStatus.COMPLETED.getCode());
                        record.setFileUrl(param.getFileUrl());
                        record.setDuration(param.getDuration());
                    } else {
                        record.setStatus(TtsStatus.FAILED.getCode());
                        record.setErrorMessage(param.getErrorMessage());
                    }

                    // 计算任务耗时（包含等待）
                    long durationWithWait = ChronoUnit.MILLIS.between(record.getCreatedTime(), now);
                    record.setTaskDurationWithWait(durationWithWait);

                    // 计算实际处理时间（不包含等待）
                    if (record.getProcessStartTime() == null) {
                        return Mono.error(new CommonException("任务未正确开始，缺少开始时间"));
                    }
                    long durationWithoutWait = ChronoUnit.MILLIS.between(record.getProcessStartTime(), now);
                    record.setTaskDurationWithoutWait(durationWithoutWait);

                    return ttsRecordRepository.save(record);
                })
                .map(TtsRecordVo::from)
                .doOnSuccess(vo -> log.info("TTS任务完成，ID: {}, 状态: {}",
                        vo.getId(), vo.getStatus()))
                .doOnError(e -> log.error("完成TTS任务失败，ID: {}",
                        param.getRecordId(), e));
    }

    @Override
    public Flux<TtsRecordVo> getPendingTasks() {
        return ttsRecordRepository.findByStatusOrderByCreatedTimeAsc(TtsStatus.PENDING.getCode())
                .map(TtsRecordVo::from)
                .doOnComplete(() -> log.debug("获取待开始任务列表完成"))
                .doOnError(e -> log.error("获取待开始任务列表失败", e));
    }

    @Override
    @Deprecated
    public Mono<TtsRecordVo> markAsProcessing(Long id) {
        // 已废弃，调用新的startTask方法
        return startTask(id);
    }

    @Override
    public Mono<TtsRecordVo> startTask(Long id) {
        CheckUtil.checkNotNull(id, new CommonException("任务ID不能为空"));

        return ttsRecordRepository.findById(id)
                .switchIfEmpty(Mono.error(new CommonException("任务不存在")))
                .flatMap(record -> {
                    if (!TtsStatus.PENDING.getCode().equals(record.getStatus())) {
                        return Mono.error(new CommonException("任务状态不正确，当前状态: " + record.getStatus()));
                    }

                    LocalDateTime now = LocalDateTime.now();
                    record.setStatus(TtsStatus.PROCESSING.getCode());
                    record.setProcessStartTime(now);
                    return ttsRecordRepository.save(record);
                })
                .map(TtsRecordVo::from)
                .doOnSuccess(vo -> log.info("任务开始执行，ID: {}，开始时间: {}",
                        vo.getId(), vo.getProcessStartTime()))
                .doOnError(e -> log.error("开始执行任务失败，ID: {}", id, e));
    }
}
